package tum0r.webengine.models.utils.vercode

import java.awt.Color
import java.awt.Graphics2D
import java.awt.image.BufferedImage
import java.io.File
import java.util.*
import javax.imageio.ImageIO

/**
 * 说明: 验证码基类
 *
 * 创建者: tum0r
 *
 * 时间: 2021/8/29 17:21
 */
abstract class VerificationCodeBase(val length: Int = 6, private val pointDivide: Int = 8, private val lineCount: Int = 6) {
    /**
     * 验证码答案
     */
    lateinit var answer: String

    /**
     * 验证码图片
     */
    lateinit var codeImage: BufferedImage

    /**
     * 验证码背景颜色
     */
    var backgroundColor: Color? = Color(139, 69, 19)

    /**
     * 验证码颜色
     */
    var codeColor: Color? = null

    /**
     * 干扰点颜色
     */
    var pointColor: Color? = null

    /**
     * 干扰线颜色
     */
    var lineColor: Color? = null

    /**
     * 随机对象
     */
    protected val random = Random()

    /**
     * 填充图片背景颜色
     */
    protected fun fillImage() {
        val rgb = randomColor(3).rgb
        for (x in 0 until codeImage.width) for (y in 0 until codeImage.height) codeImage.setRGB(x, y, rgb)
    }

    /**
     * 随机生成颜色
     *
     * @param[type] 颜色类型，0 验证码颜色 1 干扰掉颜色 2 干扰线颜色 3 背景色
     */
    fun randomColor(type: Int): Color {
        return when (type) {
            0 -> codeColor ?: randomColor(-1)
            1 -> pointColor ?: randomColor(-1)
            2 -> lineColor ?: randomColor(-1)
            3 -> backgroundColor ?: randomColor(-1)
            else -> Color(random.nextInt(255), random.nextInt(255), random.nextInt(255), this.random.nextInt(66) + 190)
        }
    }

    /**
     * 绘制干扰点
     */
    protected fun disturbPoint() {
        val height = codeImage.height
        val width = codeImage.width
        var count = height * width / (if (pointDivide >= 1) pointDivide else 15)
        while (count-- > 0) codeImage.setRGB(random.nextInt(width), random.nextInt(height), randomColor(1).rgb)
    }

    /**
     * 绘制干扰线
     */
    protected fun disturbLine() {
        val height = codeImage.height
        val width = codeImage.width
        val graphics = codeImage.graphics as Graphics2D
        for (i in 0 until lineCount) {
            graphics.color = randomColor(2)
            graphics.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height))
        }
    }

    /**
     * 生成验证码
     */
    abstract fun generateCode(): String

    /**
     * 获取新验证码
     *
     * @param[code] 图片显示验证码
     * @param[answer] 验证码答案
     */
    abstract fun newCode(code: String, answer: String)

    /**
     * 获取新验证码
     */
    abstract fun newCode()

    /**
     * 获取新验证码
     *
     * @param[code] 验证码，为空时生成
     */
    fun newCode(code: String) {
        val codeTemp = code.ifBlank { generateCode() }
        newCode(codeTemp, codeTemp)
    }

    /**
     * 保存验证码到文件
     *
     * @param[file] 验证码文件对象
     */
    fun save2Image(file: File) = ImageIO.write(codeImage, file.extension.ifBlank { "png" }, file)

    /**
     * 保存验证码到文件
     *
     * @param[path] 验证码文件路径
     */
    fun save2Image(path: String) = save2Image(File(path))
}